package com.xiaoqi.store.util;

import com.jcraft.jsch.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.ftpserver.ftplet.FtpException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.*;

/**
 * 解析日志
 */
public class ParseLog {

    protected static Logger log = LoggerFactory.getLogger(ParseLog.class);

    public static final String NO_FILE = "No such file";

    private ChannelSftp sftp = null;

    private Session sshSession = null;

    /* FTP账号 */
    private String username;
    /* FTP密码 */
    private String password;
    /* FTP主机 */
    private String host;
    /* FTP端口 */
    private int port;

    public  ParseLog(String host, int port, String username, String password) {
        this.host = host;
        this.port = port;
        this.username = username;
        this.password = password;
    }

    /**
     * 连接sftp服务器
     *
     * @return ChannelSftp sftp类型
     * @throws Exception
     */
    public   ChannelSftp connect()  {
        log.info("尝试连接FTP {host=" + host + ",username=" + username + ",port=" + port + "}");
        boolean connect = false;
        JSch jsch = new JSch();
        try {
            int tryCountAll = 5;
            int tryCount = 0;
            while (tryCount++ < tryCountAll && !connect) {
                if (tryCount > 1) {
                    try {
                        Thread.sleep(5000 * (tryCount - 1));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    log.info("第" + tryCount + "次尝试连接FTP服务器");
                }
                sshSession = jsch.getSession(username, host, port);
                sshSession.setPassword(password);
                Properties properties = new Properties();
                properties.put("StrictHostKeyChecking", "no");
                sshSession.setConfig(properties);
                sshSession.connect();
                Channel channel = sshSession.openChannel("sftp");
                channel.connect();
                sftp = (ChannelSftp) channel;
                if (sftp == null) {
                    log.info("FTP 服务器未连接");
                    connect = false;
                } else {
                    log.info("连接 FTP 成功！");
                    connect = true;
                }
            }
        } catch (JSchException e) {
            e.printStackTrace();
//            throw new FtpException("连接 FTP 异常 : " + e.getMessage());
        }
        return sftp;
    }


    public void createDirectoryQuietly(File file) {
        if (file != null) {
            if (!file.exists()) {
                if (!file.mkdirs()) {
                    throw new RuntimeException(file.getName() + " is invalid,can't be create directory");
                }
            }
        }
    }

    //remoteDir 是FTP上要下载的目录
    // localFile 是下载的本地目录
    public File downloadFileNew(String remoteDir, String localFile) throws FtpException {
        long startTime = System.currentTimeMillis();
        connect();  //连接ftp
        log.info("开始下载文件FTP目录 " + remoteDir + " 本地文件 " + localFile);
        File file = null;
        file = new File(localFile);
       /* if (file.exists()) {

            deleteFileAll(file);
        }
        file.mkdirs();*/
        createDirectoryQuietly(file);//创建目录文件，(这个方法可以创建目录，但多层级的我没试，大家定义路径的时候可以 /home/test  home是本来就有的test会创建)
        OutputStream output = null;
        try {

            /***
             * 得到custInfo路径下所有文件名
             */
            sftp.cd(remoteDir);  //进入remoteDir目录
            String path = remoteDir + "/bin";
            Vector v = sftp.ls(path);   //获取bin下文件列表
            List<String> filenameNew = new ArrayList<>(); //获取custInfo下所有目录文件名
            if (v.size() > 0) {
                log.info("文件个数不为0，开始下载。。。。。。。。。filesize=" + v.size());
                Iterator it = v.iterator();
                while (it.hasNext()) {   //循环文件
                    ChannelSftp.LsEntry lsentry = (ChannelSftp.LsEntry) it.next();
                    String filenames = lsentry.getFilename();
                    if (!".".equals(filenames) && !"..".equals(filenames)) {
                        log.info(path + "路径下的文件名" + filenames);
                        filenameNew.add(filenames);
                    }
                }
            } else {
                log.info("获取文件失败 " + remoteDir + "文件数为0");
                throw new FtpException("获取文件失败 " + remoteDir + "文件数为0");
            }

            /***
             * 得到custInfo/路径下各个文件下的文件名
             */
            sftp.cd(path);  //切换到custInfo/路径下
            for (int i = 0; i < filenameNew.size(); i++) {  //得到每个目录文件下的文件
                System.out.println(filenameNew.get(i) + "文件名");
                Vector<?> vNew = sftp.ls(filenameNew.get(i));  //获取文件列表
                sftp.cd(filenameNew.get(i)); //切换到custInfo/路径下各个文件路径下
                File file2=new File(localFile+"/"+filenameNew.get(i));
                if (file2.exists()) {
                    file2.delete();
                }
                file2.mkdir();
                if (vNew.size() > 0) {
                    Iterator it = vNew.iterator();
                    while (it.hasNext()) {
                        ChannelSftp.LsEntry lsentry = (ChannelSftp.LsEntry) it.next();
                        String filenames1 = lsentry.getFilename();
                        if (!".".equals(filenames1) && !"..".equals(filenames1)) {
                            log.info(filenameNew.get(i) + "路径下的文件名" + filenames1);
                            File file1 = new File(file2+"/"+filenames1);
                            file1.createNewFile();
                            output = new FileOutputStream(file1);
                            sftp.get(filenames1, output);
                            log.info("文件:" + filenames1 + " 下载成功.");
                        }
                    }
                    sftp.cd(path);  //每次路径下载后再切换到 上一级目录
                }
            }
        } catch (SftpException e) {
            if (e.toString().equals(NO_FILE)) {
                log.info("下载文件失败");
                throw new FtpException("下载文件失败");
            }
            throw new FtpException("ftp目录或者文件异常，检查ftp目录和文件" + e.toString());
        } catch (FileNotFoundException e) {
            throw new FtpException("本地目录异常，请检查" + file.getPath() + e.getMessage());
        } catch (IOException e) {
            throw new FtpException("创建本地文件失败" + file.getPath() + e.getMessage());
        } finally {
            if (output != null) {
                try {
                    output.close();
                } catch (IOException e) {
                    throw new FtpException("Close stream error." + e.getMessage());
                }
            }
        }
        log.info("下载文件结束 耗时:" + (System.currentTimeMillis() - startTime) + " ms");
        return file;
    }


}
